﻿//*********************************************************************
//
//  文件名：UserService
//
//  作者： LW
//
//  作用：
//
//  日期：2015/9/15 10:11:57
//
//*********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YouTravel.DomainModels;
using EntityFramework.Data.Core;
using IRepositories.Core;
using YouTravel.Framework.Enums;
using Framework.Common.Paged;
using YouTravel.QueryModels;
using Framework.Common;
using YouTravel.Framework.ResourceMessage;
using Framework.Common.Exceptions;
using YouTravel.Framework.Const;
using YouTravel.ViewModels;
using System.Linq.Expressions;
using System.Data.Entity;
namespace YouTravel.DomainService
{
    /// <summary>
    /// UserService
    /// </summary>
    public class UserService : IUserService
    {
        readonly IEFRepository<User> _userRepository;
        readonly IEFRepository<Branch> _baranchRepository;
        readonly IEFRepository<Special> _specialRepository;
        readonly IEFRepository<Menu> _menuRepository;
        public UserService(IUnitOfWork db,
            IEFRepository<User> userRepository,
            IEFRepository<Branch> baranchRepository,
            IEFRepository<Special> specialRepository,
            IEFRepository<Menu> menuRepository)
        {
            this._userRepository = userRepository;
            this._baranchRepository = baranchRepository;
            this._specialRepository = specialRepository;
            this._menuRepository = menuRepository;
            this._menuRepository.SetDbContext(db);
            this._userRepository.SetDbContext(db);
            this._baranchRepository.SetDbContext(db);
            this._specialRepository.SetDbContext(db);
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="account">账号</param>
        /// <param name="pwd">密码：调用前需加密</param>
        /// <returns></returns>
        public UserViewModel Login(string account, string pwd)
        {
            #region valid
            if (string.IsNullOrWhiteSpace(account))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "用户名"));
            if (string.IsNullOrWhiteSpace(pwd))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "密码"));

            if (!account.ValidateLen(32))
                throw new DataValidationException("用户名长度在1-20个字符");
            if (!pwd.ValidateLen(32))
                throw new DataValidationException("密码长度在1-20个字符");
            #endregion

            var tmp = this._userRepository.GetModel(c => c.Login == account && c.Status != UserStatus.AccountCancellation)
                .Include(p => p.Branch)
                .Include(p => p.Special)
                .Include(p => p.Menus)
                .ToList();
            if (tmp == null || tmp.Count() <= 0)
            { throw new BusinessException(BusinessResourceMessage.LoginFail); }

            tmp = tmp.Where(c => c.PassWord == pwd).ToList();
            if (tmp == null || tmp.Count() <= 0)
            { throw new BusinessException(BusinessResourceMessage.LoginFail); }

            var single = tmp.Where(c => c.Status == UserStatus.Normal).FirstOrDefault();
            if (single == null)
            { throw new BusinessException(BusinessResourceMessage.LoginFailFrozenA); }

            if ((int)single.Type != 0)
            {
                //机构、分社
                if (single.Type == UserType.Company || single.Type == UserType.Branch)
                {
                    if (!single.Branch.Status)
                    { throw new BusinessException(BusinessResourceMessage.LoginFailFrozenB); }
                }
                //专线
                if (single.Type == UserType.SpecialLine)
                {
                    if (single.Special.Status != SpecialStatus.Normal)
                    { throw new BusinessException(BusinessResourceMessage.LoginFailFrozenB); }
                    if (!single.IsSpecialManager)
                    {
                        //如果是专线普通账号 则移除账号管控权限
                        if (single.Menus.Where(c => c.Code == "200").Count() > 0)
                            single.Menus.Remove(single.Menus.SingleOrDefault(c => c.Code == "200"));
                        if (single.Menus.Where(c => c.Code == "201").Count() > 0)
                            single.Menus.Remove(single.Menus.SingleOrDefault(c => c.Code == "201"));
                    }
                }
            }
            var t = single.MapNew<User, UserViewModel>("Menus");
            t.Menus = single.Menus.Select((s) => new MenuViewModel()
            {
                ID = s.ID,
                Name = s.Name,
                PID = s.ParentMenu == null ? 0 : s.ParentMenu.ID,
                Sort = s.Sort,
                Url = s.Url,
                UserMenu = s.UserMenu
            });

            return t;
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="oldPwd">旧密码</param>
        /// <param name="newPwd">新密码</param>
        /// <param name="newPwdConfirm">确认新密码</param>
        /// <param name="operateUserId">操作人ID</param>
        public void ChangePassword(int userId, string oldPwd, string newPwd, string newPwdConfirm, int operateUserId)
        {
            #region valid
            if (userId <= 0)
                throw new DataValidationException(string.Format(BusinessResourceMessage.ItemCanNotNull, "用户ID"));
            if (string.IsNullOrWhiteSpace(oldPwd))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "旧密码"));
            if (string.IsNullOrWhiteSpace(newPwd))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "新密码"));
            if (string.IsNullOrWhiteSpace(newPwdConfirm))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "确认密码"));
            if (newPwd != newPwdConfirm)
                throw new DataValidationException("确认密码输入错误");

            if (!oldPwd.ValidateLen(32))
                throw new DataValidationException("旧密码长度在1-20个字符");
            if (!newPwd.ValidateLen(32))
                throw new DataValidationException("新密码长度在1-20个字符");
            if (!newPwdConfirm.ValidateLen(32))
                throw new DataValidationException("确认密码长度在1-20个字符");
            #endregion

            User single = this._userRepository.GetModelTracking().Where(c => c.ID == userId && c.Status == UserStatus.Normal).SingleOrDefault();
            if (single == null)
                throw new BusinessException("用户不存在");

            if (single.PassWord != oldPwd)
                throw new BusinessException("旧密码不正确");

            if (single.PassWord == newPwd)
                throw new BusinessException("新密码不能与旧密码相同");

            single.PassWord = newPwd;
            single.UpdaterId = operateUserId;
            single.UpdateTime = DateTime.Now;

            this._userRepository.Update(single);
        }

        /// <summary>
        /// 账号设置
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="relName">真实姓名</param>
        /// <param name="phone">手机号码</param>
        /// <param name="operateUserId">操作人ID</param>
        public void AccountSet(int userId, string phone, int operateUserId)
        {
            #region valid
            if (userId <= 0)
                throw new BusinessException(string.Format(BusinessResourceMessage.ItemCanNotNull, "用户ID"));
            if (string.IsNullOrWhiteSpace(phone))
                throw new BusinessException(string.Format(BusinessResourceMessage.PleaseInput, "手机号码"));

            if (!phone.ValidateLen(11))
                throw new DataValidationException("手机号码长度在1-11个字符");
            #endregion

            User single = this._userRepository.GetModelTracking().Where(c => c.ID == userId && c.Status == UserStatus.Normal).SingleOrDefault();
            if (single == null)
                throw new BusinessException("用户不存在");

            var count = this._userRepository.GetModel().Where(c => c.Status != UserStatus.AccountCancellation && c.Phone == phone).Count();
            if (count > 0)
                throw new BusinessException("手机号已存在");

            single.Phone = phone;
            single.UpdaterId = operateUserId;
            single.UpdateTime = DateTime.Now;

            this._userRepository.Update(single);
        }

        /// <summary>
        /// 账号添加 
        /// 注:前端传入分社与专线编号都用 BranchId 
        ///    通过 登录人Type 判断添加的用户类型
        /// </summary>
        /// <param name="user"></param>
        /// <param name="operateUserId"></param>
        public void AccountAdd(UserViewModel user, int operateUserId)
        {
            #region 验证
            if (user == null)
                throw new DataValidationException(string.Format(BusinessResourceMessage.ItemCanNotNull, "传入参数"));
            if (!user.Name.ValidateLen(20))
                throw new DataValidationException("真实姓名长度在1-20个汉字");
            if (!user.Login.ValidateLen(20))
                throw new DataValidationException("登录账号不能超过20个字符");
            if (!CommonValidator.isMobile(user.Phone))
                throw new DataValidationException("请输入正确的手机号码");
            if (user.Type <= 0 || !user.BranchId.HasValue)
                throw new DataValidationException("请选择机构");


            #endregion

            if (_userRepository.GetModel().Any(p => p.Login.Equals(user.Login)
                && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze)))
                throw new BusinessException("用户名已存在,请重新输入");
            if (_userRepository.GetModel().Any(p => p.Phone.Equals(user.Phone)
                && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze)))
                throw new BusinessException("用户手机号已存在,请重新输入");

            var operateUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);
            var model = new User();
            model.Login = user.Login;
            model.PassWord = CommonMD5.getInstance().Get2MD5(BusinessConst._PASSWORD);
            model.Name = user.Name;
            model.IsSpecialManager = user.IsSpecialManager;
            //当操作员为总公司时添加账号则为分社
            //操作员为总公司时 分社所属机构为操作员ID
            switch (operateUser.Type)
            {
                case UserType.Company:
                    if (user.Type != UserType.Branch)
                        throw new DataOperationPermissions("无此操作权限,总公司只能添加分社账号");
                    model.Type = UserType.Branch;
                    model.BranchId = user.BranchId;

                    break;
                case UserType.Branch:
                    if (user.Type != UserType.SpecialLine)
                        throw new DataOperationPermissions("无此操作权限,分社只能添加专线账号");
                    model.Type = UserType.SpecialLine;
                    model.SpecialId = user.BranchId;

                    break;
                case UserType.SpecialLine:
                    //当登录人为专线操作员时
                    if (!operateUser.IsSpecialManager)
                        throw new DataOperationPermissions("无此操作权限,专线操作员不能操作账号管控所有权限");
                    //登录人 与添加专线不一致时
                    if (operateUser.SpecialId != user.BranchId)
                        throw new DataOperationPermissions("无此操作权限,专线管理员只能操作自己所属专线");
                    //当添加用户为管理员时
                    if (user.IsSpecialManager)
                        throw new DataOperationPermissions("无此操作权限,专线管理员只能添加专线操作员账号");
                    model.Type = UserType.SpecialLine;
                    model.SpecialId = user.BranchId;

                    break;
                default:
                    model.Type = user.Type;
                    switch (user.Type)
                    {
                        case UserType.Branch:
                            model.BranchId = user.BranchId;
                            break;
                        case UserType.SpecialLine:
                            model.SpecialId = user.BranchId;
                            break;
                        default:
                            throw new BusinessException("数据异常,不存在此数据");
                    }
                    break;
            }


            model.Status = UserStatus.Normal;
            model.Phone = user.Phone;

            model.CreaterId = operateUserId;
            model.CreateTime = DateTime.Now;
            model.UpdaterId = operateUserId;
            model.UpdateTime = DateTime.Now;
            #region 设置默认权限
            var value = (int)model.Type;
            var listMenu = _menuRepository.GetModelTracking().Where(p => ((p.UserMenu & value) == value)).ToList();
            model.Menus = listMenu;
            #endregion




            BuidDataAuthorityVerify(operateUserId, model);

            _userRepository.Insert(model);
        }

        /// <summary>
        /// 账号更新
        /// 注:只能更新手机 此处权限不控制
        ///    现业务正常情况只能自己更新自己的
        /// </summary>
        /// <param name="user"></param>
        /// <param name="operateUserId"></param>
        public void AccountUpdate(UserViewModel user, int operateUserId)
        {
            if (user.ID != operateUserId)
                throw new DataOperationPermissions("无此操作权限,只能修改自己信息");
            if (!_userRepository.GetModel().Any(p => p.ID == user.ID && p.Status == UserStatus.Normal)) throw new BusinessException("此账号不存在");
            DateTime dt = DateTime.Now;
            _userRepository.Update(p => p.ID == user.ID, u => new User() { Phone = user.Phone, UpdaterId = operateUserId, UpdateTime = dt });

            #region 更新缓存
            var loginUser = RedisHelp.GetLoginUserCache(user.ID);
            if (loginUser != null)
            {
                loginUser.Status = user.Status;
                RedisHelp.RefreshLoginUserCache(loginUser);
            }
            #endregion
        }

        /// <summary>
        /// 账号启用禁用
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="operateUserId"></param>
        public void AccountEnabled(int userId, int operateUserId)
        {

            var user = _userRepository.GetModel().SingleOrDefault(p => p.ID == userId && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze));
            if (user == null) throw new BusinessException("此账号不存在");

            if (user.Status == UserStatus.Normal)
                user.Status = UserStatus.Freeze;
            else
                user.Status = UserStatus.Normal;

            user.UpdaterId = operateUserId;
            user.UpdateTime = DateTime.Now;

            BuidDataAuthorityVerify(operateUserId, user);

            _userRepository.Update(p => p.ID == user.ID, u => new User { UpdaterId = user.UpdaterId, UpdateTime = user.UpdateTime, Status = user.Status });

            #region 更新缓存
            var loginUser = RedisHelp.GetLoginUserCache(userId);
            if (loginUser != null)
            {
                loginUser.Status = user.Status;
                RedisHelp.RefreshLoginUserCache(loginUser);
            }
            #endregion

        }

        /// <summary>
        /// 账号销户
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="operateUserId"></param>
        public void AccountCancellation(int userId, int operateUserId)
        {
            var user = _userRepository.GetModel().SingleOrDefault(p => p.ID == userId && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze));
            if (user == null)
                throw new BusinessException("此账号不存在");

            BuidDataAuthorityVerify(operateUserId, user);

            _userRepository.Update(p => p.ID == userId, u => new User { Status = UserStatus.AccountCancellation });

            #region 更新缓存
            var loginUser = RedisHelp.GetLoginUserCache(userId);
            if (loginUser != null)
            {
                loginUser.Status = user.Status;
                RedisHelp.RefreshLoginUserCache(loginUser);
            }
            #endregion
        }

        /// <summary>
        /// 设置权限
        /// </summary>
        /// <param name="user"></param>
        /// <param name="operateUserId"></param>
        public void SetAuthorityAccount(UserViewModel user, int operateUserId)
        {

            var model = _userRepository.GetModelTracking()
                .Include(p => p.Menus).FirstOrDefault(p => p.ID == user.ID && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze));

            if (model == null) throw new BusinessException("此账号不存在");
            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);

            BuidDataAuthorityVerify(operateUserId, model);

            model.Menus.Clear();
            //当权限值不为空时
            if (user.Menus != null && user.Menus.Any())
            {
                //注:用户得到 自己的权限
                int value = (int)model.Type;

                var listMenu = _menuRepository.GetModelTracking().Where(p => ((p.UserMenu & value) == value)).ToList();

                List<string> errMgs = new List<string>();
                foreach (var item in user.Menus)
                {
                    var menu = listMenu.FirstOrDefault(p => p.ID == item.ID);
                    if (menu == null)
                    {
                        errMgs.Add(item.Name);
                    }
                    else
                    {
                        model.Menus.Add(menu);
                        //用户不为专线时
                        //要添加一级菜单
                        if (model.Type != UserType.SpecialLine)
                        {
                            var upMenu = listMenu.FirstOrDefault(p => p.ID == menu.UpMenuId);
                            if (upMenu == null)
                                throw new BusinessException("菜单权限值设置有误,除专线以外的角色都有一级菜单权限");
                            //不存在一级菜单时 添加
                            if (model.Menus.All(p => p.ID != upMenu.ID))
                                model.Menus.Add(upMenu);
                        }
                    }
                }
                if (errMgs.Any())
                {
                    throw new DataOperationPermissions(string.Format("此用户不能设置{0}权限", string.Join(",", errMgs)));
                }
            }
            _userRepository.Update(model);

            #region 更新缓存
            var updateUser = RedisHelp.GetLoginUserCache(user.ID);
            if (updateUser != null)
            {
                updateUser.Menus = user.Menus;
                RedisHelp.RefreshLoginUserCache(updateUser);
            }
            #endregion
        }

        /// <summary>
        /// 得到 单个用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public UserViewModel GetModel(int userId)
        {
            var user = _userRepository.GetModel().Include(p => p.Branch).Include(p => p.Special)
                .FirstOrDefault(p => p.ID == userId && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze));
            if (user == null) throw new BusinessException("此账号不存在");


            return Mapper.MapNew<User, UserViewModel>(user);
        }

        /// <summary>
        /// 得到 用户 权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public UserViewModel GetAccountAuthority(int userId)
        {
            var user = _userRepository.GetModel()
                .Include(p => p.Menus)
                .FirstOrDefault(p => p.ID == userId && (p.Status == UserStatus.Normal || p.Status == UserStatus.Freeze));
            if (user == null) throw new BusinessException("此账号不存在");

            var userViewModel = user.MapNew<User, UserViewModel>("Menus");

            //注:用户得到 自己的权限
            int value = (int)user.Type;

            //得到用户所有权限
            var listDbMeun = _menuRepository.GetModel()
                .Include(p => p.ParentMenu)
                .Where(p => ((p.UserMenu & value) == value)).ToList();

            var listMeun = listDbMeun.Select(s => new MenuViewModel()
            {
                ID = s.ID,
                Name = s.Name,
                PID = s.ParentMenu == null ? 0 : s.ParentMenu.ID,
                Sort = s.Sort,
                IsHas = false,
                ParentMenu = s.ParentMenu == null ? null : new MenuViewModel()
                {
                    ID = s.ParentMenu.ID,
                    Name = s.ParentMenu.Name,
                    PID = 0,
                    Sort = s.ParentMenu.Sort,
                    IsHas = true
                }
            }).ToList();
            //设置用户已有权限
            foreach (var item in listMeun)
            {
                if (user.Menus.Any(p => p.ID == item.ID))
                    item.IsHas = true;
            }
            var tempListMenu = new List<MenuViewModel>();
            foreach (var item in listMeun)
            {
                tempListMenu.Add(item);
                if (item.PID != 0 && tempListMenu.All(p => p.ID != item.PID))
                    tempListMenu.Add(item.ParentMenu);
            }

            userViewModel.Menus = tempListMenu;

            return userViewModel;
        }

        /// <summary>
        /// 得到用户所有相应菜单权限
        /// 注:在此处做限制 根据登录人不同 返回不同的菜单
        /// </summary>
        /// <param name="operateUserId"></param>
        /// <returns></returns>
        public List<MenuViewModel> GetMenuByLoginUser(int operateUserId)
        {
            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);
            if (loginUser.Type == UserType.SpecialLine && !loginUser.IsSpecialManager)
                throw new DataOperationPermissions("无此操作权限,专线操作员不能操作账号管控所有权限");

            //超级管理员为0 查询所有

            int value = 0;
            switch (loginUser.Type)
            {
                case UserType.Company:
                    value = (int)UserType.Branch;
                    break;
                case UserType.Branch:
                    value = (int)UserType.SpecialLine;
                    break;
                case UserType.SpecialLine:
                    value = (int)UserType.SpecialLine;
                    break;
            }

            return _menuRepository.GetModel().Where(p => ((p.UserMenu & value) == value)).Select(s => new MenuViewModel()
            {
                ID = s.ID,
                Name = s.Name,
                PID = s.ParentMenu == null ? 0 : s.ParentMenu.ID,
                Sort = s.Sort,
            }).ToList();
        }

        /// <summary>
        /// 查询得到列表
        /// </summary>
        /// <param name="queryCond"></param>
        /// <returns></returns>
        public CustomPagedList<UserViewModel> GetList(PagedParam<UserQuery> queryCond)
        {
            return _userRepository.GetModel()
                .Include(p => p.Special)
                .Include(p => p.Branch)
                .GetPagedList(queryCond.PageDto.PageNo,
                queryCond.PageDto.PageSize, BuildQueryCondition(queryCond.QueryDto),
                queryCond.SortField).ToCustomPagedList(u =>
                {
                    var s = u.MapNew<User, UserViewModel>("Menus");
                    s.Branch = u.Branch.MapNew<Branch, BranchViewModel>();
                    s.Special = u.Special.MapNew<Special, SpecialViewModel>();
                    return s;
                });

        }

        /// <summary>
        /// 得到机构下拉列表
        /// </summary>
        /// <param name="operateUserId"></param>
        /// <returns></returns>
        public List<ComboxData> GetOrgCombox(int operateUserId)
        {
            List<ComboxData> list = new List<ComboxData>();
            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);
            //总公司查询出所有分社
            if (loginUser.Type == UserType.Company)
            {
                var baranchList = _baranchRepository.GetModel(p => p.Type == BranchType.Branch && p.Status).Select(s => new { s.ID, s.Name }).ToList();
                foreach (var item in baranchList)
                {
                    list.Add(new ComboxData()
                    {
                        Key = item.ID,
                        Value = item.Name,
                        ExtValue = new
                        {
                            Type = UserType.Branch
                        }
                    });
                }
            }//分社查询出下级所有专线
            else if (loginUser.Type == UserType.Branch)
            {
                var specialList = _specialRepository
                    .GetModel(p => p.BranchId == loginUser.BranchId && (p.Status == SpecialStatus.Normal))
                    .Select(s => new { s.ID, s.Name }).ToList();
                foreach (var item in specialList)
                {
                    list.Add(new ComboxData()
                    {
                        Key = item.ID,
                        Value = item.Name,
                        ExtValue = new
                        {
                            Type = UserType.SpecialLine
                        }
                    });
                }
            }//专线管理员查询出本专线所属专线
            else if (loginUser.Type == UserType.SpecialLine)
            {
                if (loginUser.IsSpecialManager)
                {
                    var specialList = _specialRepository
                        .GetModel(p => p.ID == loginUser.SpecialId && (p.Status == SpecialStatus.Normal))
                        .Select(s => new { s.ID, s.Name }).ToList();
                    foreach (var item in specialList)
                    {
                        list.Add(new ComboxData()
                        {
                            Key = item.ID,
                            Value = item.Name,
                            ExtValue = new
                            {
                                Type = UserType.SpecialLine
                            }
                        });
                    }
                }
                else
                {
                    throw new DataOperationPermissions("无此操作权限,专线操作员不能操作账号管控所有权限");
                }
            } //查询 所有 
            else
            {
                var specialList = _specialRepository
                    .GetModel(p => (p.Status == SpecialStatus.Normal || p.Status == SpecialStatus.Freeze))
                    .Select(s => new { s.ID, s.Name }).ToList();
                var baranchList = _baranchRepository
                    .GetModel(p => p.Type == BranchType.Branch && p.Status)
                    .Select(s => new { s.ID, s.Name }).ToList();
                foreach (var item in baranchList)
                {
                    list.Add(new ComboxData()
                    {
                        Key = item.ID,
                        Value = item.Name,
                        ExtValue = new
                        {
                            Type = UserType.Branch
                        }
                    });
                }
                foreach (var item in specialList)
                {
                    list.Add(new ComboxData()
                    {
                        Key = item.ID,
                        Value = item.Name,
                        ExtValue = new
                        {
                            Type = UserType.SpecialLine
                        }
                    });
                }
            }
            return list;
        }
        #region private

        private Func<IQueryable<User>, IQueryable<User>> BuildQueryCondition(UserQuery userQuery)
        {
            return query =>
            {


                //不能查询出超级管理员
                query = query.Where(p => p.BranchId != null || p.SpecialId != null);

                //注:账号状态查询所有 不受分社 与专线状态限制
                //query = query.Where(p => (p.BranchId != null && p.Branch.Status) || (p.Special != null && p.Special.Status == SpecialStatus.Normal));

                if (userQuery != null)
                {
                    var loginUser = RedisHelp.GetLoginUserCacheNotNull(userQuery.LoginUserId);

                    //根据登录人类别查询
                    //总公司只能显示和管理分社的成员帐号不管理专线，
                    //分社只能显示和管理本机构下的专线帐号，
                    //专线管理员只能显示管理本专线下的专线帐号并且只能设置专线功能模块权限
                    if (userQuery.OrgId.HasValue)
                    {
                        if (!userQuery.Type.HasValue)
                            throw new QueryArgumentException("参数有误,传入机构时必须传入类型参数");

                        if (loginUser.Type == UserType.Company)
                        {
                            query = query.Where(p => p.BranchId == userQuery.OrgId);
                        }
                        else if (loginUser.Type == UserType.Branch)
                        {
                            //传入的OrgId是否为登录分社的下级专线
                            if (!_specialRepository.GetModel().Any(p => p.BranchId == loginUser.BranchId && p.ID == userQuery.OrgId.Value))
                            {
                                throw new DataOperationPermissions("无此操作权限,分社只能查看下级专线");
                            }
                            query = query.Where(p => p.SpecialId == userQuery.OrgId.Value);
                        }
                        else if (loginUser.Type == UserType.SpecialLine)
                        {
                            if (!loginUser.IsSpecialManager)
                            {
                                throw new DataOperationPermissions("无此操作权限,专线操作员不能查看账号列表");
                            }
                            //登录人为专线管理员时，只能查询本专线下的专线账号
                            if (loginUser.SpecialId != userQuery.OrgId)
                            {
                                throw new DataOperationPermissions("当前登录人为专线管理员，只能查询本专线下的账号");
                            }
                            query = query.Where(p => p.SpecialId == userQuery.OrgId);
                        }
                        else
                        {
                            if (userQuery.Type.Value == UserType.Branch)
                                query = query.Where(p => p.BranchId == userQuery.OrgId.Value);
                            if (userQuery.Type.Value == UserType.SpecialLine)
                                query = query.Where(p => p.SpecialId == userQuery.OrgId.Value);
                        }
                    }
                    else//没选择机构时
                    {
                        if (loginUser.Type == UserType.Company)//总公司只能显示和管理分社的成员帐号不管理专线
                        {
                            query = query.Where(p => p.Type == UserType.Branch);
                        }
                        else if (loginUser.Type == UserType.Branch)//分社只能显示和管理本机构下的专线帐号
                        {
                            query = query.Where(p => (p.Special.BranchId == loginUser.BranchId
                                && p.Type == UserType.SpecialLine));
                        }
                        else if (loginUser.Type == UserType.SpecialLine)//专线管理员只能显示管理本专线下的专线帐号
                        {
                            if (!loginUser.IsSpecialManager)
                            {
                                throw new DataOperationPermissions("无此操作权限,专线操作员不能查看账号列表");
                            }
                            query = query.Where(p => p.SpecialId == loginUser.SpecialId.Value
                                && p.Type == UserType.SpecialLine);
                        }
                        else
                        {
                            if (userQuery.Type.HasValue)
                            {
                                if (userQuery.Type.Value == UserType.Branch)
                                    query = query.Where(p => p.BranchId == userQuery.OrgId.Value);
                                if (userQuery.Type.Value == UserType.SpecialLine)
                                    query = query.Where(p => p.SpecialId == userQuery.OrgId.Value);
                            }
                        }
                    }


                    if (!string.IsNullOrEmpty(userQuery.UserName))
                        query = query.Where(p => p.Name.Contains(userQuery.UserName) || p.Login.Contains(userQuery.UserName));
                    if (userQuery.UserStatus != null)
                        query = query.Where(p => p.Status == userQuery.UserStatus);

                }


                return query;
            };
        }

        /// <summary>
        /// 数据权限验证   在数据保存前验证
        /// 总公司         只能操作分社
        /// 分社           只能操作他下属专线
        /// 专线管理员     只能操作自己所属专线
        /// 专线操作员     没有操作账号管控权限
        /// 超级管理员     能操作所有数据
        /// </summary>
        /// <param name="operateUserId">登录人</param>
        /// <param name="user">操作数据</param>
        private void BuidDataAuthorityVerify(int operateUserId, User user)
        {
            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);
            if (loginUser.Type == UserType.Company)
            {
                if (user.Type != UserType.Branch)
                    throw new DataOperationPermissions("无此操作权限,总公司只能操作分社");
            }
            if (loginUser.Type == UserType.Branch)
            {
                //分社保能操作专线 并且 还是下属专线
                if (user.Type != UserType.SpecialLine)
                    throw new DataOperationPermissions("无此操作权限,分社只能操作他下属专线");
                if (!_specialRepository.GetModel().Any(p => p.BranchId == loginUser.BranchId && p.ID == user.SpecialId))
                    throw new DataOperationPermissions("无此操作权限,分社只能操作他下属专线");
            }
            if (loginUser.Type == UserType.SpecialLine)
            {
                if (!loginUser.IsSpecialManager)
                    throw new DataOperationPermissions("无此操作权限,专线操作员不能操作账号管控所有权限");
                if (user.Type != UserType.SpecialLine)
                    throw new DataOperationPermissions("无此操作权限,专线管理员只能操作专线数据");
                if (user.SpecialId != loginUser.SpecialId)
                    throw new DataOperationPermissions("无此操作权限,专线管理员只能操作自己所属专线数据");
            }

        }
        #endregion
        /// <summary>
        /// 忘记密码
        /// 初始化为6个0
        /// </summary>
        /// <param name="forgetPwd">密码信息</param>
        public void ForgetPassword(ForgetPasswordViewModel forgetPwd)
        {
            #region valid
            if (string.IsNullOrWhiteSpace(forgetPwd.phone))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "手机号码"));
            if (string.IsNullOrWhiteSpace(forgetPwd.newpwd))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "重置密码"));
            if (string.IsNullOrWhiteSpace(forgetPwd.confirmpwd))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "确认密码"));
            if (forgetPwd.newpwd != forgetPwd.confirmpwd)
                throw new DataValidationException("确认密码输入错误");
            if (!forgetPwd.newpwd.ValidateLen(32))
                throw new DataValidationException("重置密码长度在1-20个字符");
            if (!forgetPwd.confirmpwd.ValidateLen(32))
                throw new DataValidationException("确认密码长度在1-20个字符");
            #endregion

            var tmp = _userRepository.GetModelTracking().Where(c => c.Phone == forgetPwd.phone && c.Status != UserStatus.AccountCancellation)
                //.Include(p => p.Branch)
                //.Include(p => p.Special)
                .ToList();
            if (tmp == null || !tmp.Any())
            { throw new BusinessException("手机号码不存在，请输入正确的手机号码"); }

            var single = tmp.FirstOrDefault(c => c.Status == UserStatus.Normal);
            if (single == null)
            { throw new BusinessException("手机号码不存在，请输入正确的手机号码"); }

            single.PassWord = CommonMD5.getInstance().Get2MD5(forgetPwd.newpwd);

            _userRepository.Update(single);
        }
        /// <summary>
        /// 验证手机是否存在
        /// </summary>
        /// <param name="phone"></param>
        /// <returns></returns>
        public bool CheckPhone(string phone)
        {
            #region valid
            if (string.IsNullOrWhiteSpace(phone))
                throw new DataValidationException(string.Format(BusinessResourceMessage.PleaseInput, "手机号码"));
            #endregion

            var tmp = _userRepository.GetModelTracking().Where(c => c.Phone == phone && c.Status != UserStatus.AccountCancellation)
                .ToList();
            if (tmp == null || !tmp.Any())
            { throw new BusinessException("手机号码不存在，请输入正确的手机号码"); }

            var single = tmp.FirstOrDefault(c => c.Status == UserStatus.Normal);
            if (single == null)
            { throw new BusinessException("手机号码不存在，请输入正确的手机号码"); }

            return true;
        }
    }
}